﻿@page
@{
    ViewBag.Title = "SVG";
}
<svg xmlns="http://www.w3.org/2000/svg"
     viewBox="0 0 30 20"
     onload="makeDraggable(evt)">

    <style>
        .static {
            cursor: not-allowed;
        }

        .draggable {
            cursor: move;
        }
    </style>

    <script type="text/javascript">
        function makeDraggable(evt) {
            var svg = evt.target;

            svg.addEventListener('mousedown', startDrag);
            svg.addEventListener('mousemove', drag);
            svg.addEventListener('mouseup', endDrag);
            svg.addEventListener('mouseleave', endDrag);
            svg.addEventListener('touchstart', startDrag);
            svg.addEventListener('touchmove', drag);
            svg.addEventListener('touchend', endDrag);
            svg.addEventListener('touchleave', endDrag);
            svg.addEventListener('touchcancel', endDrag);

            var selectedElement, offset, transform,
                bbox, minX, maxX, minY, maxY, confined;

            var boundaryX1 = 10.5;
            var boundaryX2 = 30;
            var boundaryY1 = 2.2;
            var boundaryY2 = 19.2;

            function getMousePosition(evt) {
                var CTM = svg.getScreenCTM();
                if (evt.touches) { evt = evt.touches[0]; }
                return {
                    x: (evt.clientX - CTM.e) / CTM.a,
                    y: (evt.clientY - CTM.f) / CTM.d
                };
            }

            function startDrag(evt) {
                if (evt.target.classList.contains('draggable')) {
                    selectedElement = evt.target;
                    offset = getMousePosition(evt);

                    // Make sure the first transform on the element is a translate transform
                    var transforms = selectedElement.transform.baseVal;

                    if (transforms.length === 0 || transforms.getItem(0).type !== SVGTransform.SVG_TRANSFORM_TRANSLATE) {
                        // Create an transform that translates by (0, 0)
                        var translate = svg.createSVGTransform();
                        translate.setTranslate(0, 0);
                        selectedElement.transform.baseVal.insertItemBefore(translate, 0);
                    }

                    // Get initial translation
                    transform = transforms.getItem(0);
                    offset.x -= transform.matrix.e;
                    offset.y -= transform.matrix.f;

                    confined = evt.target.classList.contains('confine');
                    if (confined) {
                        bbox = selectedElement.getBBox();
                        minX = boundaryX1 - bbox.x;
                        maxX = boundaryX2 - bbox.x - bbox.width;
                        minY = boundaryY1 - bbox.y;
                        maxY = boundaryY2 - bbox.y - bbox.height;
                    }
                }
            }

            function drag(evt) {
                if (selectedElement) {
                    evt.preventDefault();

                    var coord = getMousePosition(evt);
                    var dx = coord.x - offset.x;
                    var dy = coord.y - offset.y;

                    if (confined) {
                        if (dx < minX) { dx = minX; }
                        else if (dx > maxX) { dx = maxX; }
                        if (dy < minY) { dy = minY; }
                        else if (dy > maxY) { dy = maxY; }
                    }

                    transform.setTranslate(dx, dy);
                }
            }

            function endDrag(evt) {
                selectedElement = false;
            }
        }
    </script>

    <rect x="0" y="0" width="30" height="20" fill="#eee" />
    <rect x="10.5" y="2.2" width="19.5" height="17" fill="#bbb" />

    <rect class="static" fill="#888" x="2" y="4" width="6" height="2" />
    <rect class="draggable" fill="#007bff" x="4" y="11" width="2" height="6" />
    <ellipse class="draggable confine" fill="#ff00af" cx="5" cy="5" rx="3" ry="2" transform="translate(10, 0)" />
    <polygon class="draggable confine" fill="#ffa500" points="16.9 15.6 17.4 18.2 15 17 12.6 18.2 13.1 15.6 11.2 13.8 13.8 13.4 15 11 16.2 13.4 18.8 13.8" />
    <path class="draggable" stroke="#2bad7b" stroke-width="0.5" fill="none" d="M1 5C5 1 5 9 9 5" transform="translate(20)" />
    <text class="draggable confine" x="25" y="15" text-anchor="middle" font-size="3px" alignment-baseline="middle">Drag</text>
</svg>
